package com.eidos.blogs.common.utils;

import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author ： Eidos
 * @date ：Created in 2020/12/28
 * @description：
 * @modified By：
 * @version: 1.0
 */
@Component
public class RedisUtils<T> {
    @Resource(
            name = "redisTemplate"
    )
    private RedisTemplate<String, T> redisTemplate;

    public RedisUtils() {
    }

    public RedisTemplate<String, T> getRedisTemplate() {
        return this.redisTemplate;
    }

    public void setValueSerializer(RedisSerializer<T> serializer) {
        this.setValueSerializer(this.getRedisTemplate(), serializer);
    }

    public void setValueSerializer(RedisTemplate<String, T> redisTemplate, RedisSerializer<T> serializer) {
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashValueSerializer(serializer);
    }

    public void set(String key, T val) {
        this.set(this.getRedisTemplate(), key, val);
    }

    public void set(RedisTemplate<String, T> redisTemplate, String key, T val) {
        redisTemplate.opsForValue().set(key, val);
    }

    public Boolean setIfAbsent(String key, T val) {
        return this.setIfAbsent(this.getRedisTemplate(), key, val);
    }

    public Boolean setIfAbsent(RedisTemplate<String, T> redisTemplate, String key, T val) {
        return redisTemplate.opsForValue().setIfAbsent(key, val);
    }

    public Boolean setIfPresent(String key, T val) {
        return this.setIfPresent(this.getRedisTemplate(), key, val);
    }

    public Boolean setIfPresent(RedisTemplate<String, T> redisTemplate, String key, T val) {
        return redisTemplate.opsForValue().setIfPresent(key, val);
    }

    public void set(String key, T val, long expire) {
        this.set(this.getRedisTemplate(), key, val, expire);
    }

    public void set(RedisTemplate<String, T> redisTemplate, String key, T val, long expire) {
        redisTemplate.opsForValue().set(key, val, expire, TimeUnit.SECONDS);
    }

    public Boolean setIfAbsent(String key, T val, long expire) {
        return this.setIfAbsent(this.getRedisTemplate(), key, val, expire);
    }

    public Boolean setIfAbsent(RedisTemplate<String, T> redisTemplate, String key, T val, long expire) {
        return redisTemplate.opsForValue().setIfAbsent(key, val, expire, TimeUnit.SECONDS);
    }

    public Boolean setIfPresent(String key, T val, long expire) {
        return this.setIfPresent(this.getRedisTemplate(), key, val, expire);
    }

    public Boolean setIfPresent(RedisTemplate<String, T> redisTemplate, String key, T val, long expire) {
        return redisTemplate.opsForValue().setIfPresent(key, val, expire, TimeUnit.SECONDS);
    }

    public void multiSet(Map<String, T> map) {
        this.multiSet(this.getRedisTemplate(), map);
    }

    public void multiSet(RedisTemplate<String, T> redisTemplate, Map<String, T> map) {
        redisTemplate.opsForValue().multiSet(map);
    }

    public Boolean multiSetIfAbsent(Map<String, T> map) {
        return this.multiSetIfAbsent(this.getRedisTemplate(), map);
    }

    public Boolean multiSetIfAbsent(RedisTemplate<String, T> redisTemplate, Map<String, T> map) {
        return redisTemplate.opsForValue().multiSetIfAbsent(map);
    }

    public Boolean expire(String key, long expire) {
        return this.expire(this.getRedisTemplate(), key, expire);
    }

    public Boolean expire(RedisTemplate<String, T> redisTemplate, String key, long expire) {
        return redisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }

    public Long getExpire(String key) {
        return this.getExpire(this.getRedisTemplate(), key);
    }

    public Long getExpire(RedisTemplate<String, T> redisTemplate, String key) {
        return redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);
    }

    public T getAndSet(String key, T value) {
        return this.getAndSet(this.getRedisTemplate(), key, value);
    }

    public T getAndSet(RedisTemplate<String, T> redisTemplate, String key, T value) {
        return redisTemplate.opsForValue().getAndSet(key, value);
    }

    public T get(String key) {
        return this.get(this.getRedisTemplate(), key);
    }

    public T get(RedisTemplate<String, T> redisTemplate, String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * @deprecated
     */
    @Deprecated
    public Set<String> getkeys(String pattern) {
        return this.getkeys(this.getRedisTemplate(), pattern);
    }

    /**
     * @deprecated
     */
    @Deprecated
    public Set<String> getkeys(RedisTemplate<String, T> redisTemplate, String pattern) {
        return redisTemplate.keys(pattern);
    }

    /**
     * @deprecated
     */
    @Deprecated
    public List<T> getByPattern(String pattern) {
        return this.getByPattern(this.getRedisTemplate(), pattern);
    }

    /**
     * @deprecated
     */
    @Deprecated
    public List<T> getByPattern(RedisTemplate<String, T> redisTemplate, String pattern) {
        return this.multiGet(redisTemplate, this.getkeys(redisTemplate, pattern));
    }

    public List<T> multiGet(Collection<String> keys) {
        return this.multiGet(this.getRedisTemplate(), keys);
    }

    public List<T> multiGet(RedisTemplate<String, T> redisTemplate, Collection<String> keys) {
        return redisTemplate.opsForValue().multiGet(keys);
    }

    public List<T> getByPrefix(String prefix) {
        return this.getByPrefix(this.getRedisTemplate(), prefix);
    }

    public List<T> getByPrefix(RedisTemplate<String, T> redisTemplate, String prefix) {
        return this.getByPattern(redisTemplate, prefix + "*");
    }

    public Boolean delete(String key) {
        return this.delete(this.getRedisTemplate(), key);
    }

    public Boolean delete(RedisTemplate<String, T> redisTemplate, String key) {
        return redisTemplate.delete(key);
    }

    public Long delete(Set<String> keys) {
        return this.delete(this.getRedisTemplate(), keys);
    }

    public Long delete(RedisTemplate<String, T> redisTemplate, Set<String> keys) {
        return redisTemplate.delete(keys);
    }

    public Long deleteByPrex(String prefix) {
        return this.deleteByPrex(this.getRedisTemplate(), prefix);
    }

    public Long deleteByPrex(RedisTemplate<String, T> redisTemplate, String prefix) {
        return this.delete(redisTemplate, this.getkeys(redisTemplate, prefix + "*"));
    }

    public Boolean hasKey(String key) {
        return this.hasKey(this.getRedisTemplate(), key);
    }

    public Boolean hasKey(RedisTemplate<String, T> redisTemplate, String key) {
        return redisTemplate.hasKey(key);
    }

    public Long increment(String key) {
        return this.increment(this.getRedisTemplate(), key);
    }

    public Long increment(RedisTemplate<String, T> redisTemplate, String key) {
        return redisTemplate.opsForValue().increment(key);
    }

    public Long increment(String key, long delta) {
        return this.increment(this.getRedisTemplate(), key, delta);
    }

    public Long increment(RedisTemplate<String, T> redisTemplate, String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    public Long decrement(String key) {
        return this.decrement(this.getRedisTemplate(), key);
    }

    public Long decrement(RedisTemplate<String, T> redisTemplate, String key) {
        return redisTemplate.opsForValue().decrement(key);
    }

    public Long decrement(String key, long delta) {
        return this.decrement(this.getRedisTemplate(), key, delta);
    }

    public Long decrement(RedisTemplate<String, T> redisTemplate, String key, long delta) {
        return redisTemplate.opsForValue().decrement(key, delta);
    }

    public <HK> void hput(String key, HK hashKey, T value) {
        this.hput(this.getRedisTemplate(), key, hashKey, value);
    }

    public <HK> void hput(RedisTemplate<String, T> redisTemplate, String key, HK hashKey, T value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    public <HK> T hget(String key, HK hashKey) {
        return this.hget(this.getRedisTemplate(), key, hashKey);
    }

    public <HK> T hget(RedisTemplate<String, T> redisTemplate, String key, HK hashKey) {
        HashOperations<String, HK, T> ho = redisTemplate.opsForHash();
        return ho.get(key, hashKey);
    }

    public <HK> List<T> hmultiGet(String key, Collection<HK> hashKeys) {
        return this.hmultiGet(this.getRedisTemplate(), key, hashKeys);
    }

    public <HK> List<T> hmultiGet(RedisTemplate<String, T> redisTemplate, String key, Collection<HK> hashKeys) {
        HashOperations<String, HK, T> ho = redisTemplate.opsForHash();
        return ho.multiGet(key, hashKeys);
    }

    public <HK> void hputAll(String key, Map<? extends HK, ? extends T> map) {
        this.hputAll(this.getRedisTemplate(), key, map);
    }

    public <HK> void hputAll(RedisTemplate<String, T> redisTemplate, String key, Map<? extends HK, ? extends T> map) {
        redisTemplate.opsForHash().putAll(key, map);
    }

    public <HK> Boolean hputIfAbsent(String key, HK hashKey, T value) {
        return this.hputIfAbsent(this.getRedisTemplate(), key, hashKey, value);
    }

    public <HK> Boolean hputIfAbsent(RedisTemplate<String, T> redisTemplate, String key, HK hashKey, T value) {
        return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
    }

    public <HK> Map<HK, T> enrtris(String key) {
        return this.enrtris(this.getRedisTemplate(), key);
    }

    public <HK> Map<HK, T> enrtris(RedisTemplate<String, T> redisTemplate, String key) {
        HashOperations<String, HK, T> ho = redisTemplate.opsForHash();
        return ho.entries(key);
    }

    public <HK> Long hdelete(String key, HK... hashKeys) {
        return this.hdelete(this.getRedisTemplate(), key, hashKeys);
    }

    public <HK> Long hdelete(RedisTemplate<String, T> redisTemplate, String key, HK... hashKeys) {
        return redisTemplate.opsForHash().delete(key, hashKeys);
    }

    public <HK> Boolean hasKey(String key, HK hashKey) {
        return this.hasKey(this.getRedisTemplate(), key, hashKey);
    }

    public <HK> Boolean hasKey(RedisTemplate<String, T> redisTemplate, String key, HK hashKey) {
        return redisTemplate.opsForHash().hasKey(key, hashKey);
    }

    public <HK> Set<HK> hkeys(String key) {
        return this.hkeys(this.getRedisTemplate(), key);
    }

    public <HK> Set<HK> hkeys(RedisTemplate<String, T> redisTemplate, String key) {
        HashOperations<String, HK, T> ho = redisTemplate.opsForHash();
        return ho.keys(key);
    }

    public <HK> List<T> hvalues(String key) {
        return this.hvalues(this.getRedisTemplate(), key);
    }

    public <HK> List<T> hvalues(RedisTemplate<String, T> redisTemplate, String key) {
        HashOperations<String, HK, T> ho = redisTemplate.opsForHash();
        return ho.values(key);
    }

    public <HK> Long hincrement(String key, HK hashKey, long delta) {
        return this.hincrement(this.getRedisTemplate(), key, hashKey, delta);
    }

    public <HK> Long hincrement(RedisTemplate<String, T> redisTemplate, String key, HK hashKey, long delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    public <HK> Double hincrement(String key, HK hashKey, double delta) {
        return this.hincrement(this.getRedisTemplate(), key, hashKey, delta);
    }

    public <HK> Double hincrement(RedisTemplate<String, T> redisTemplate, String key, HK hashKey, double delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    public Long hsize(String key) {
        return this.hsize(this.getRedisTemplate(), key);
    }

    public Long hsize(RedisTemplate<String, T> redisTemplate, String key) {
        return redisTemplate.opsForHash().size(key);
    }

    public void renameKey(String oldKey, String newKey) {
        this.renameKey(this.getRedisTemplate(), oldKey, newKey);
    }

    public void renameKey(RedisTemplate<String, T> redisTemplate, String oldKey, String newKey) {
        redisTemplate.rename(oldKey, newKey);
    }

    public Set<T> members(String key) {
        return this.members(this.getRedisTemplate(), key);
    }

    public Set<T> members(RedisTemplate<String, T> redisTemplate, String key) {
        return redisTemplate.opsForSet().members(key);
    }

    public Long addSet(String key, T... values) {
        return this.addSet(this.getRedisTemplate(), key, values);
    }

    public Long addSet(RedisTemplate<String, T> redisTemplate, String key, T... values) {
        return redisTemplate.opsForSet().add(key, values);
    }

    public Long removeSet(String key, T... values) {
        return this.removeSet(this.getRedisTemplate(), key, values);
    }

    public Long removeSet(RedisTemplate<String, T> redisTemplate, String key, T... values) {
        return redisTemplate.opsForSet().remove(key, values);
    }

    public String ping() {
        return this.ping(this.getRedisTemplate());
    }

    public String ping(RedisTemplate<String, T> redisTemplate) {
        return (String) redisTemplate.execute((RedisCallback<Object>) (connection) -> {
            return connection.ping();
        });
    }
}
